import { isArray } from './is'

export function bind (fn, ctx) {
  function boundFn (a) {
    const len = arguments.length
    return len ? (len > 1 ? fn.apply(ctx, arguments) : fn.call(ctx, a)) : fn.call(ctx)
  }

  boundFn._length = fn.length
  return boundFn
}

export function bindAll (obj, ctx) {
  if (typeof obj !== 'object') return
  if (isArray(obj)) return obj.map((fn) => bind(fn, ctx))
  Object.keys(obj).forEach((key) => { obj[key] = bind(obj[key], ctx) })
  return obj
}

/**
 * 展开 object
 * @param ob
 * @returns {{}}
 */
export function flattenObject (ob) {
  const toReturn = {}

  for (const i in ob) {
    if (!ob.hasOwnProperty(i)) continue
    if ((typeof ob[i]) === 'object') {
      const flatObject = flattenObject(ob[i])
      for (const x in flatObject) {
        if (!flatObject.hasOwnProperty(x)) continue

        toReturn[i + '.' + x] = flatObject[x]
      }
    } else {
      toReturn[i] = ob[i]
    }
  }
  return toReturn
}

export function makeUnEnumerable (obj, key, value) {
  Object.defineProperty(obj, key, {
    enumerable: false,
    configurable: false,
    writable: true,
    ... (value ? { value } : {})
  },)
}

/**
 * Convert an Array-like object to a real Array.
 * @param list
 * @param start
 * @returns {Array}
 */
export function toArray (list, start) {
  start = start || 0
  let i = list.length - start
  const ret = new Array(i)
  while (i--) {
    ret[i] = list[i + start]
  }
  return ret
}
